home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / tcp_ip / os2 / pmnos11s / telnet.old < prev    next >
Text File  |  1993-07-30  |  11KB  |  542 lines

  1. /* Internet Telnet client
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. /* Mods by PA0GRI */
  5. #include <stdio.h>
  6. #include <errno.h>
  7. #ifdef    __TURBOC__
  8. #include <io.h>
  9. #include <fcntl.h>
  10. #endif
  11. #include "global.h"
  12. #include "config.h"
  13. #include "mbuf.h"
  14. #include "socket.h"
  15. #include "telnet.h"
  16. #include "session.h"
  17. #include "proc.h"
  18. #include "tty.h"
  19. #include "commands.h"
  20. #include "netuser.h"
  21.  
  22. static int filemode __ARGS((FILE *fp,int mode));
  23. #define    CTLZ    26
  24.  
  25. int Refuse_echo = 0;
  26. int Tn_cr_mode = 0;    /* if true turn <cr> to <cr-nul> */
  27.  
  28. #ifdef    DEBUG
  29. char *T_options[] = {
  30.     "Transmit Binary",
  31.     "Echo",
  32.     "",
  33.     "Suppress Go Ahead",
  34.     "",
  35.     "Status",
  36.     "Timing Mark"
  37. };
  38. #endif
  39.  
  40. #ifdef    MAILBOX
  41. /* Execute user BBS command */
  42. int
  43. dobbs(argc,argv,p)
  44. int argc;
  45. char *argv[];
  46. void *p;
  47. {
  48.     struct session *sp;
  49.     struct sockaddr_in fsocket;
  50.  
  51.     /*Make sure this comes from console - WG7J*/
  52.     if(Curproc->input != Command->input)
  53.         return 0;
  54.  
  55.     /* Allocate a session descriptor */
  56.     if((sp = newsession("Local BBS",TELNET,0)) == NULLSESSION){
  57.         tputs(TooManySessions);
  58.         return 1;
  59.     }
  60.     fsocket.sin_family = AF_INET;
  61.     if(argc < 3)
  62.         fsocket.sin_port = IPPORT_TELNET;
  63.     else
  64.         fsocket.sin_port = atoi(argv[2]);
  65.  
  66.     if((fsocket.sin_addr.s_addr = Ip_addr) == 0){
  67.         tprintf(Badhost,sp->name);
  68.         keywait(NULLCHAR,1);
  69.         freesession(sp);
  70.         return 1;
  71.     }
  72.     if((sp->s = socket(AF_INET,SOCK_STREAM,0)) == -1){
  73.         tputs(Nosock);
  74.         keywait(NULLCHAR,1);
  75.         freesession(sp);
  76.         return 1;
  77.     }
  78.     return tel_connect(sp,(char *)&fsocket,SOCKSIZE);
  79. }
  80. #endif /*MAILBOX*/
  81.  
  82. #ifdef ALLSESSIONS
  83. /* Execute user telnet command */
  84. int
  85. dotelnet(argc,argv,p)
  86. int argc;
  87. char *argv[];
  88. void *p;
  89. {
  90.     struct session *sp;
  91.     struct sockaddr_in fsocket;
  92.  
  93.     /*Make sure this comes from console - WG7J*/
  94.     if(Curproc->input != Command->input)
  95.         return 0;
  96.  
  97.     /* Allocate a session descriptor */
  98.     if((sp = newsession(argv[1],TELNET,0)) == NULLSESSION){
  99.         tputs(TooManySessions);
  100.         return 1;
  101.     }
  102.     fsocket.sin_family = AF_INET;
  103.     if(argc < 3)
  104.         fsocket.sin_port = IPPORT_TELNET;
  105.     else
  106.         fsocket.sin_port = atoi(argv[2]);
  107.  
  108.     tprintf("Resolving %s... ",sp->name);
  109.     if((fsocket.sin_addr.s_addr = resolve(sp->name)) == 0){
  110.         tprintf(Badhost,sp->name);
  111.         keywait(NULLCHAR,1);
  112.         freesession(sp);
  113.         return 1;
  114.     }
  115.     if((sp->s = socket(AF_INET,SOCK_STREAM,0)) == -1){
  116.         tputs(Nosock);
  117.         keywait(NULLCHAR,1);
  118.         freesession(sp);
  119.         return 1;
  120.     }
  121.     return tel_connect(sp,(char *)&fsocket,SOCKSIZE);
  122. }
  123. #endif
  124.  
  125. #ifdef ALLSERV
  126. /* Execute user ttylink command */
  127. int
  128. dottylink(argc,argv,p)
  129. int argc;
  130. char *argv[];
  131. void *p;
  132. {
  133.     struct session *sp;
  134.     struct sockaddr_in fsocket;
  135.  
  136.     /* Allocate a session descriptor */
  137.     if((sp = newsession(argv[1],TELNET,1)) == NULLSESSION){
  138.         tputs(TooManySessions);
  139.         return 1;
  140.     }
  141.     fsocket.sin_family = AF_INET;
  142.     if(argc < 3)
  143.         fsocket.sin_port = IPPORT_TTYLINK;
  144.     else
  145.         fsocket.sin_port = atoi(argv[2]);
  146.  
  147.     tprintf("Resolving %s... ",sp->name);
  148.     if((fsocket.sin_addr.s_addr = resolve(sp->name)) == 0){
  149.         tprintf(Badhost,sp->name);
  150.         keywait(NULLCHAR,1);
  151.         freesession(sp);
  152.         return 1;
  153.     }
  154.     if((sp->s = socket(AF_INET,SOCK_STREAM,0)) == -1){
  155.         tputs(Nosock);
  156.         keywait(NULLCHAR,1);
  157.         freesession(sp);
  158.         return 1;
  159.     }
  160.     return tel_connect(sp,(char *)&fsocket,SOCKSIZE);
  161. }
  162. #endif /*ALLSERV*/
  163.  
  164. /* Generic interactive connect routine, used by Telnet, AX.25, NET/ROM */
  165. int
  166. tel_connect(sp,fsocket,len)
  167. struct session *sp;
  168. char *fsocket;
  169. int len;
  170. {
  171.     unsigned int index;
  172.     struct telnet tn;
  173.  
  174.     index = sp - Sessions;
  175.     memset((char *)&tn,0,sizeof(tn));
  176.     tn.eolmode = Tn_cr_mode;
  177.     tn.session = sp;    /* Upward pointer */
  178.     sp->cb.telnet = &tn;    /* Downward pointer */
  179.     sockmode(sp->s,SOCK_ASCII);    /* Default to ascii mode */
  180.  
  181.     tprintf("Trying %s...\n",psocket((struct sockaddr *)fsocket));
  182.     if(connect(sp->s,fsocket,len) == -1){
  183.           tprintf("%s session %u failed: %s errno %d\n",
  184.          Sestypes[sp->type], index, sockerr(sp->s),errno);
  185.  
  186.         keywait(NULLCHAR,1);
  187.         freesession(sp);
  188.         return 1;
  189.     }
  190.     tprintf("%s session ",Sestypes[sp->type]);
  191.     tprintf("%u connected to %s\n",index,sp->name);
  192.     tnrecv(&tn);
  193.     return 0;
  194. }
  195.  
  196. /* Telnet input routine, common to both telnet and ttylink */
  197. void
  198. tnrecv(tn)
  199. struct telnet *tn;
  200. {
  201.     int c,s,index;
  202.     struct session *sp;
  203.     char *cp;
  204.  
  205.     sp = tn->session;
  206.     s = sp->s;
  207.  
  208.     index = sp - Sessions;
  209.  
  210.     /* Fork off the transmit process */
  211.     sp->proc1 = newproc("tel_out",1024,tel_output,0,tn,NULL,0);
  212.  
  213.     /* Process input on the connection */
  214.     while((c = recvchar(s)) != -1){
  215.         if(c != IAC){
  216. #ifdef notdef
  217.             /* Allow international character sets to pass - WG7J */
  218.             /* Ordinary character */
  219.             if(!tn->remote[TN_TRANSMIT_BINARY])
  220.                 c &= 0x7f;
  221. #endif
  222.             tputc((char)c);
  223.             continue;
  224.         }
  225.         /* IAC received, get command sequence */
  226.         c = recvchar(s);
  227.         switch(c){
  228.         case WILL:
  229.             c = recvchar(s);
  230.             willopt(tn,c);
  231.             break;
  232.         case WONT:
  233.             c = recvchar(s);
  234.             wontopt(tn,c);
  235.             break;
  236.         case DO:
  237.             c = recvchar(s);
  238.             doopt(tn,c);
  239.             break;
  240.         case DONT:
  241.             c = recvchar(s);
  242.             dontopt(tn,c);
  243.             break;
  244.         case IAC:    /* Escaped IAC */
  245.             tputc(IAC);
  246.             break;
  247.         }
  248.     }
  249. quit:    /* A close was received from the remote host.
  250.      * Notify the user, kill the output task and wait for a response
  251.      * from the user before freeing the session.
  252.      */
  253.     sockmode(sp->output,SOCK_ASCII); /* Restore newline translation */
  254.     cp = sockerr(s);
  255.     tprintf("%s session %u", Sestypes[sp->type],index);
  256.     tprintf(" closed: %s\n", cp != NULLCHAR ? cp : "EOF");
  257.     /*killproc(sp->proc1);*/
  258.     alert(sp->proc1, EABORT);
  259.     sp->proc1 = NULLPROC;
  260.     close_s(sp->s);
  261.     sp->s = -1;
  262.     keywait(NULLCHAR,1);
  263.     freesession(sp);
  264. }
  265.  
  266. /* User telnet output task, started by user telnet command */
  267. void
  268. tel_output(unused,tn1,p)
  269. int unused;
  270. void *tn1;
  271. void *p;
  272. {
  273.     struct session *sp;
  274.     int c;
  275.     struct telnet *tn;
  276.  
  277.     tn = (struct telnet *)tn1;
  278.     sp = tn->session;
  279.  
  280.     /* Send whatever's typed on the terminal */
  281.     while((c = recvchar(sp->input)) != EOF){
  282.         if (errno == EABORT)
  283.             break;
  284.         usputc(sp->s,(char)c);
  285.         if(!tn->remote[TN_ECHO] && sp->record != NULLFILE)
  286.             putc(c,sp->record);
  287.  
  288.         /* By default, output is transparent in remote echo mode.
  289.          * If eolmode is set, turn a cr into cr-null.
  290.          * This can only happen when in remote echo (raw) mode, since
  291.          * the tty driver normally maps \r to \n in cooked mode.
  292.          */
  293.         if(c == '\r' && tn->eolmode)
  294.             usputc(sp->s,'\0');
  295.  
  296.         if(tn->remote[TN_ECHO])
  297.             usflush(sp->s);
  298.     }
  299.     /* Make sure our parent doesn't try to kill us after we exit */
  300.     sp->proc1 = NULLPROC;
  301. }
  302. int
  303. doecho(argc,argv,p)
  304. int argc;
  305. char *argv[];
  306. void *p;
  307. {
  308.     if(argc < 2){
  309.         if(Refuse_echo)
  310.             tprintf("Refuse\n");
  311.         else
  312.             tprintf("Accept\n");
  313.     } else {
  314.         if(argv[1][0] == 'r')
  315.             Refuse_echo = 1;
  316.         else if(argv[1][0] == 'a')
  317.             Refuse_echo = 0;
  318.         else
  319.             return -1;
  320.     }
  321.     return 0;
  322. }
  323. /* set for unix end of line for remote echo mode telnet */
  324. int
  325. doeol(argc,argv,p)
  326. int argc;
  327. char *argv[];
  328. void *p;
  329. {
  330.     if(argc < 2){
  331.         if(Tn_cr_mode)
  332.             tprintf("null\n");
  333.         else
  334.             tprintf("standard\n");
  335.     } else {
  336.         if(argv[1][0] == 'n')
  337.             Tn_cr_mode = 1;
  338.         else if(argv[1][0] == 's')
  339.             Tn_cr_mode = 0;
  340.         else {
  341.             tprintf("Usage: %s [standard|null]\n",argv[0]);
  342.             return -1;
  343.         }
  344.     }
  345.     return 0;
  346. }
  347.  
  348. /* The guts of the actual Telnet protocol: negotiating options */
  349. void
  350. willopt(tn,opt)
  351. struct telnet *tn;
  352. int opt;
  353. {
  354.     int ack;
  355.  
  356. #ifdef    DEBUG
  357.     tprintf("recv: will ");
  358.     if(uchar(opt) <= NOPTIONS)
  359.         tprintf("%s\n",T_options[opt]);
  360.     else
  361.         tprintf("%u\n",opt);
  362. #endif
  363.     
  364.     switch(uchar(opt)){
  365.     case TN_TRANSMIT_BINARY:
  366.     case TN_ECHO:
  367.     case TN_SUPPRESS_GA:
  368.         if(tn->remote[uchar(opt)] == 1)
  369.             return;        /* Already set, ignore to prevent loop */
  370.         if(uchar(opt) == TN_ECHO){
  371.             if(Refuse_echo){
  372.                 /* User doesn't want to accept */
  373.                 ack = DONT;
  374.                 break;
  375.             } else {
  376.                 /* Put tty into raw mode */
  377.                 tn->session->ttystate.edit = 0;
  378.                 tn->session->ttystate.echo = 0;
  379.                 sockmode(tn->session->s,SOCK_BINARY);
  380.                 sockmode(tn->session->input,SOCK_BINARY);
  381.                 sockmode(tn->session->output,SOCK_BINARY);
  382.                 if(tn->session->record != NULLFILE)
  383.                     filemode(tn->session->record,SOCK_BINARY);
  384.  
  385.             }
  386.         }
  387.         tn->remote[uchar(opt)] = 1;
  388.         ack = DO;            
  389.         break;
  390.     default:
  391.         ack = DONT;    /* We don't know what he's offering; refuse */
  392.     }
  393.     answer(tn,ack,opt);
  394. }
  395. void
  396. wontopt(tn,opt)
  397. struct telnet *tn;
  398. int opt;
  399. {
  400. #ifdef    DEBUG
  401.     tprintf("recv: wont ");
  402.     if(uchar(opt) <= NOPTIONS)
  403.         tprintf("%s\n",T_options[uchar(opt)]);
  404.     else
  405.         tprintf("%u\n",uchar(opt));
  406. #endif
  407.     if(uchar(opt) <= NOPTIONS){
  408.         if(tn->remote[uchar(opt)] == 0)
  409.             return;        /* Already clear, ignore to prevent loop */
  410.         tn->remote[uchar(opt)] = 0;
  411.         if(uchar(opt) == TN_ECHO){
  412.             /* Put tty into cooked mode */
  413.             tn->session->ttystate.edit = 1;
  414.             tn->session->ttystate.echo = 1;
  415.             sockmode(tn->session->s,SOCK_ASCII);
  416.             sockmode(tn->session->input,SOCK_ASCII);
  417.             sockmode(tn->session->output,SOCK_ASCII);
  418.             if(tn->session->record != NULLFILE)
  419.                 filemode(tn->session->record,SOCK_ASCII);
  420.         }
  421.     }
  422.     answer(tn,DONT,opt);    /* Must always accept */
  423. }
  424. void
  425. doopt(tn,opt)
  426. struct telnet *tn;
  427. int opt;
  428. {
  429.     int ack;
  430.  
  431. #ifdef    DEBUG
  432.     tprintf("recv: do ");
  433.     if(uchar(opt) <= NOPTIONS)
  434.         tprintf("%s\n",T_options[uchar(opt)]);
  435.     else
  436.         tprintf("%u\n",uchar(opt));
  437. #endif
  438.     switch(uchar(opt)){
  439.     case TN_SUPPRESS_GA:
  440.         if(tn->local[uchar(opt)] == 1)
  441.             return;        /* Already set, ignore to prevent loop */
  442.         tn->local[uchar(opt)] = 1;
  443.         ack = WILL;
  444.         break;
  445.     default:
  446.         ack = WONT;    /* Don't know what it is */
  447.     }
  448.     answer(tn,ack,opt);
  449. }
  450. void
  451. dontopt(tn,opt)
  452. struct telnet *tn;
  453. int opt;
  454. {
  455. #ifdef    DEBUG
  456.     tprintf("recv: dont ");
  457.     if(uchar(opt) <= NOPTIONS)
  458.         tprintf("%s\n",T_options[uchar(opt)]);
  459.     else
  460.         tprintf("%u\n",uchar(opt));
  461. #endif
  462.     if(uchar(opt) <= NOPTIONS){
  463.         if(tn->local[uchar(opt)] == 0){
  464.             /* Already clear, ignore to prevent loop */
  465.             return;
  466.         }
  467.         tn->local[uchar(opt)] = 0;
  468.     }
  469.     answer(tn,WONT,opt);
  470. }
  471. void
  472. answer(tn,r1,r2)
  473. struct telnet *tn;
  474. int r1,r2;
  475. {
  476.     char s[3];
  477.  
  478. #ifdef    DEBUG
  479.     switch(r1){
  480.     case WILL:
  481.         tprintf("sent: will ");
  482.         break;
  483.     case WONT:
  484.         tprintf("sent: wont ");
  485.         break;
  486.     case DO:
  487.         tprintf("sent: do ");
  488.         break;
  489.     case DONT:
  490.         tprintf("sent: dont ");
  491.         break;
  492.     }
  493.     if(r2 <= NOPTIONS)
  494.         tprintf("%s\n",T_options[r2]);
  495.     else
  496.         tprintf("%u\n",r2);
  497. #endif
  498.  
  499.     s[0] = IAC;
  500.     s[1] = r1;
  501.     s[2] = r2;
  502.     send(tn->session->s,s,3,0);
  503. }
  504. #ifdef    __TURBOC__
  505. /* Set end-of-line translation mode on file */
  506. static int
  507. filemode(fp,mode)
  508. FILE *fp;
  509. int mode;
  510. {
  511.     int omode;
  512.  
  513.     if(fp == NULLFILE)
  514.         return -1;
  515.  
  516.     if(fp->flags & _F_BIN)
  517.         omode = SOCK_BINARY;
  518.     else
  519.         omode = SOCK_ASCII;
  520.  
  521.     switch(mode){
  522.     case SOCK_BINARY:
  523.         fp->flags = _F_BIN;
  524.         setmode(fileno(fp),O_BINARY);
  525.         break;
  526.     case SOCK_ASCII:
  527.         fp->flags &= ~_F_BIN;
  528.         setmode(fileno(fp),O_TEXT);
  529.         break;
  530.     }
  531.     return omode;
  532. }
  533. #else
  534. static int
  535. filemode(fp,mode)
  536. FILE *fp;
  537. int mode;
  538. {
  539.     return 0;
  540. }
  541. #endif
  542.